package xyz.pengzhihui.androidplugin.Activities;

import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;

import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;

import xyz.pengzhihui.androidplugin.Algorithms.EdgeProcessing;
import xyz.pengzhihui.androidplugin.Envs.CameraLiveActivityBase;
import xyz.pengzhihui.androidplugin.R;
import xyz.pengzhihui.lib_fancy_ui_kit.FancyDrawerCamera.FancyItem;

//import org.opencv.android.Utils;


public class CameraLiveActivity extends CameraLiveActivityBase
{
    String path="";


    CascadeClassifier cascade=null;
    MTCNN mtcnn=null;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        // No effect
        mCameraSceneItems.put(0, new FancyItem.Builder(getApplicationContext())
                .setName("无效果")
                .setDetails("相机预览，无任何效果")
                .setIconBitmapId(R.mipmap.camera_live_icon_blank)
                .build());


        // Edge detect algorithm.
        EdgeProcessing mEdgeProcessing = new EdgeProcessing();
//        mCameraSceneItems.put(1, new FancyItem.Builder(getApplicationContext())
//                .setName("边缘检测")
//                .setDetails("这是一个使用Canny算子进行多级边缘检测的算法")
//                .setIconBitmapId(R.mipmap.camera_live_icon_canny)
//                .setOnFrameListener(new FancyItem.onFrameListener()
//                {
//                    @Override
//                    public Mat onFrame(Mat frame)
//                    {
//                        return mEdgeProcessing.doProcessing(frame);
//                    }
//                }).build());

        mCameraSceneItems.put(1, new FancyItem.Builder(getApplicationContext())
                .setName("人脸检测")
                .setDetails("人脸检测....")
                .setIconBitmapId(R.mipmap.camera_live_icon_fastface)
                .setSettingLayoutId(R.layout.layout_camera_live_algo_setting_face_detect)
                .setOnFrameListener(new FancyItem.onFrameListener(){
                    @Override
                    public Mat onFrame(Mat frame)
                    {
                        mtcnnDetect(frame);

                        return frame;
                    }
                }).build());

        // ...


        commitItems(mCameraSceneItems);
    }


    @Override
    public void onScrollerItemSelected(int selectedItemIndex)
    {
        super.onScrollerItemSelected(selectedItemIndex);

        switch (selectedItemIndex)
        {
            case 0: // No effect
                break;

            case 1: // Edge detect
                break;

            case 2:

            //...
        }
    }

    //mtcnn人脸识别
    private void mtcnnDetect(Mat frame) {
        if (mtcnn==null){
            mtcnn=new MTCNN(getAssets());
            Log.d("face666", "初始成功");
        }

        Bitmap bitmap= Bitmap.createBitmap(frame.cols(),frame.rows(),Bitmap.Config.ARGB_8888);

        org.opencv.android.Utils.matToBitmap(frame,bitmap);

        //检测人脸
        Vector<Box> boxes=mtcnn.detectFaces(bitmap,200);

//        //直接在bitmap上画然后，转回mat
//        for (int i=0;i<boxes.size();i++){
//            Utils.drawRect(bitmap,boxes.get(i).transform2Rect());
//            Utils.drawPoints(bitmap,boxes.get(i).landmark);
//        }
//        org.opencv.android.Utils.bitmapToMat(bitmap,frame);


        //直接在mat上画点
        if (boxes!=null){
            for (Box box : boxes) {
                //box.transform2Rect()
                Imgproc.rectangle(frame, new Point(box.box[0], box.box[1]), new Point(box.box[2],box.box[3]), new Scalar(0, 0, 255));
            }
        }


        //return frame;
    }

    // opencv 人脸认别
    private void cvDetect(Mat frame){
    try{
        if (path==""){
            path=copyAssetAndWrite("haarcascade_frontalface_alt.xml");
            Log.d("face666 path", path);
        }

        if (cascade==null){
            cascade= new CascadeClassifier(path);
            //在路径上没有找到相关文件返回1
            if (cascade.empty()) {
                System.out.println("人脸识别文件读取失败");
                //return;
                Log.d("face666", "人脸识别文件读取失败002");
                return;
            }else{
                Log.d("face666", "人脸识别文件读取成功");
            }
        }


        Mat gray = new Mat();
        Imgproc.cvtColor(frame, gray, Imgproc.COLOR_RGB2GRAY);//灰度

        MatOfRect rect = new MatOfRect();
        cascade.detectMultiScale(gray, rect);

//为每张识别到的人脸画一个圈
        for (Rect re : rect.toArray()) {
            Imgproc.rectangle(frame, new Point(re.x, re.y), new Point(re.x+ re.width, re.y + re.height), new Scalar(0, 0, 255));
        }

    }catch (Exception e){
        Log.d("face666", "异常:"+e.getMessage());
    }

}
    private String copyAssetAndWrite(String fileName) {
        try {
            File cacheDir = getCacheDir();
            if (!cacheDir.exists()) {
                cacheDir.mkdirs();
            }
            File outFile = new File(cacheDir, fileName);
            if (!outFile.exists()) {
                boolean res = outFile.createNewFile();
                if (!res) {
                    return null;
                }
            } else {
                if (outFile.length() > 10) {//表示已经写入一次
                    return outFile.getPath();
                }
            }
            InputStream is = getAssets().open(fileName);
            FileOutputStream fos = new FileOutputStream(outFile);
            byte[] buffer = new byte[1024];
            int byteCount;
            while ((byteCount = is.read(buffer)) != -1) {
                fos.write(buffer, 0, byteCount);
            }
            fos.flush();
            is.close();
            fos.close();
            return outFile.getPath();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

}
